﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;

namespace Protobuf_Gui
{
    public static class ConfigLoader
    {
        public static T Load<T>(string filename) where T : class
        {
            try
            {
                var fi = new FileInfo(filename);
                if (fi.Directory != null && !fi.Directory.Exists)
                {
                    fi.Directory.Create();
                    return default(T);
                }
                if (!fi.Exists)
                    return default(T);

                using (FileStream cfgFile = File.OpenRead(filename))
                {
                    return (T)new XmlSerializer(typeof(T)).Deserialize(cfgFile);
                }
            }
            catch (Exception e)
            {
                return default(T);
            }
        }

        public static T LoadBinary<T>(string filename) where T : class
        {
            try
            {
                var fi = new FileInfo(filename);
                if (fi.Directory != null && !fi.Directory.Exists)
                {
                    fi.Directory.Create();
                    return default(T);
                }
                if (!fi.Exists)
                    return default(T);

                using (FileStream cfgFile = File.OpenRead(filename))
                {
                    var formatter = new BinaryFormatter();
                    return (T)formatter.Deserialize(cfgFile);
                }
            }
            catch (Exception e)
            {
                return default(T);
            }
        }

        public static IEnumerable<T> LoadFolderBinary<T>(string folderPath) where T : class
        {
            var di = new DirectoryInfo(folderPath);
            if (!di.Exists)
            {
                di.Create();
                yield break;
            }
            var fileInfos = di.GetFiles();
            foreach (var fileInfo in fileInfos)
            {
                yield return LoadBinary<T>(fileInfo.FullName);
            }
        }


        public static IEnumerable<T> LoadFolder<T>(string folderPath) where T : class
        {
            var di = new DirectoryInfo(folderPath);
            if (!di.Exists)
            {
                di.Create();
                yield break;
            }
            var fileInfos = di.GetFiles();
            foreach (var fileInfo in fileInfos)
            {
                yield return Load<T>(fileInfo.FullName);
            }
        }

        public static bool SaveBinary(object obj, string filename)
        {
            try
            {
                var fi = new FileInfo(filename);
                if (fi.Directory != null && !fi.Directory.Exists)
                {
                    fi.Directory.Create();
                }
                else if (fi.Exists)
                    fi.Delete();

                using (FileStream cfgFile = File.OpenWrite(filename))
                {
                    var formatter = new BinaryFormatter();
                    formatter.Serialize(cfgFile, obj);
                }
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }

        public static bool Save(object obj, string filename)
        {
            try
            {
                var fi = new FileInfo(filename);
                if (fi.Directory != null && !fi.Directory.Exists)
                {
                    fi.Directory.Create();
                }
                else if (fi.Exists)
                    fi.Delete();

                using (FileStream cfgFile = File.OpenWrite(filename))
                {
                    new XmlSerializer(obj.GetType()).Serialize(cfgFile, obj);
                }
                return true;
            }
            catch (Exception e)
            {
                var message = string.Format("Failed to save {0}, Exception:", filename);
                Console.WriteLine(message);
                return false;
            }
        }

        public static void DeleteDirectoryIfExist(string fullpath)
        {
            try
            {
                var info = new DirectoryInfo(fullpath);
                info.Delete(true);
            }
            catch
            {
            }
        }


        public static void DeleteIfExist(string fullpath)
        {
            try
            {
                var info = new FileInfo(fullpath);
                if (info.Directory != null && !info.Directory.Exists)
                {
                    info.Directory.Create();
                    return;
                }
                if (info.Exists)
                {
                    info.Delete();
                }
            }
            catch (Exception e)
            {
            }
        }

        public static void EnumerateProps(object o)
        {
            var type = o.GetType();
            var properties = type.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                var method = property.GetGetMethod();
                if (method != null) method.Invoke(o, null);
            }
        }
    }
}